import numpy as np
import pandas as pd

class RecursiveLS:
    #输入样本矩阵L，输出向量y，估计参数个数num，是否有常数项aff
    def __init__(self, L, y, num, aff):
        # 给定辨识参数个数
        self.m = num
        # aff的作用是确认是否有常数项
        self.aff=aff
        if self.aff==0:
            L2 = L
        else:
            v=np.ones(L.shape[0])
            v2=v.reshape(v.shape[0],1)
            L2=np.hstack((L,v2))
        self.invL=np.linalg.inv(np.matmul(np.transpose(L2),L2))
        theta2=np.matmul(np.transpose(L2),y)
        self.theta=np.matmul(self.invL,theta2)

    # 输入样本X以及输出y，用递推最小二乘更新估计参数
    def RLS(self, X,y):
        if self.aff==0:
            X_ = X
            X_2=np.transpose(X_)
        else:
            on = np.ones(1)
            on2=on.reshape(on.shape[0],1)
            X_ = np.hstack((X, on2))
            X_2=np.transpose(X_)
        theta=np.multiply((y-np.matmul(X_,self.theta)),X_2)
        f1=(np.array([[1]])+np.matmul(X_,np.matmul(self.invL,np.transpose(X_))))
        self.theta = self.theta + np.matmul(self.invL/f1, theta)
        self.invL=self.invL-np.matmul(np.matmul(self.invL,np.transpose(X_)),np.matmul(X_,self.invL))/f1
        return self.theta


def rls_calculte(url, sheet1, sheet2):
    dfx = pd.read_excel(url, sheet_name=sheet1)
    dfy = pd.read_excel(url, sheet_name=sheet2)
    data_setx = np.array(dfx)
    data_sety = np.array(dfy)
    num = data_setx.shape[1] + 1  # 若参数中没有常数项，则换为 num=data_setx.shape[1]
    # print(num)
    phi2 = data_setx[:num]
    y = data_sety[:num]
    #构建RLS对象实例
    RLS1=RecursiveLS(phi2,y,phi2.shape[1]+1,1) #若参数中没有常数项，则换为 RLS1=RecursiveLS(phi2,y,phi2.shape[1],0)
    for i in range(data_setx.shape[0] - num):
        # 每次获取一个样本并利用RLS函数计算更新后的参数估计值
        X = [data_setx[i + num]]
        on = np.ones(1)
        on2 = on.reshape(on.shape[0], 1)
        # 获取对应样本的输出
        y = [data_sety[i + 3]]
        RLS1.RLS(X, y)
    return RLS1.theta

if __name__ =="__main__":
    #从datax中读取输入数据，从datay中读取输出数据
     pathx = 'RLS_data.xlsx'
     theta = rls_calculte(pathx, 'Sheet1', 'Sheet2')
     print(theta)